package com.kugou.internal;

import com.kugou.internal.compiler.EcjCompiler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Properties;


/**
 * Created by Alex on 2014/9/20
 */
@Component
public class SpyHelper {

    @Autowired
    private ApplicationContext applicationContext;

    private static ApplicationContext appContext;
    public static ApplicationContext getAppContext() {
        return appContext;
    }
    @PostConstruct
    public void init() {
        appContext = this.applicationContext;
    }
    /**
     * java代码转成java的类实例
     * @param javaCode java代码字符串
     * @return 由java代码生成的类实例
     * @throws Exception
     */
    public Object codeToObject(String javaCode, String mainClass) throws Exception {
        Class clazz = EcjCompiler.compileOne(javaCode, mainClass);
        Object instance = clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (isInjectAnnotationPresent(field)) {
                Object o = findBean(field);
                field.setAccessible(true);
                field.set(instance, o);
            }
        }
        return instance;
    }

    private Object findBean(Field field) {
        if (field.isAnnotationPresent(Resource.class)) {
            Resource resource = field.getAnnotation(Resource.class);
            return applicationContext.getBean(resource.name());
        } else if (field.isAnnotationPresent(Qualifier.class)) {
            Qualifier qualifier = field.getAnnotation(Qualifier.class);
            return applicationContext.getBean(qualifier.value());
        } else if (field.isAnnotationPresent(Autowired.class)) {
            if (ApplicationContext.class.isAssignableFrom(field.getType())) {
                return SpyHelper.getAppContext();
            }
            return applicationContext.getBean(field.getType());
        }
        throw new RuntimeException("依赖注入失败: " + field.getName());
    }

    /**
     * 依赖注入的那些注解是否存在， 也就是@Autowired, @Resource
     * @param field
     * @return
     */
    private boolean isInjectAnnotationPresent(Field field) {
        return field.isAnnotationPresent(Autowired.class)
                || field.isAnnotationPresent(Resource.class);
    }
    private static Properties passwds = new Properties();

    static {
        try (InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("passwd.properties")) {
            passwds.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static boolean checkAuth(String username, String passwd) {
        if (passwds.containsKey(username)) {
            try {
                return passwds.get(username).equals(stringTosha256(passwd));
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    public static String stringTosha256(String content) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");

        md.update(content.getBytes("UTF-8"));
        byte[] mdbytes = md.digest();

        //convert the byte to hex format method 2
        StringBuilder hexString = new StringBuilder();
        for (int i=0;i<mdbytes.length;i++) {
            hexString.append(Integer.toHexString(0xFF & mdbytes[i]));
        }

        return hexString.toString();
    }

}
